package com.sl.common.page;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.db.PageResult;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sl.common.util.CommonServletUtil;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.utils.Lists;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @Description: 分页类
 * @Author: MECHREVO
 * @Date: 2021/5/7 8:47
 * @Version: 1.0.0
 */
@Getter
@Setter
@ToString
@NoArgsConstructor
@Slf4j
public class PageList<E> extends ArrayList<E> {

    /**
     * 查询数据列表
     */
//    protected List<E> records = Collections.emptyList();

    /**
     * 总数
     */
    protected long total = 0;
    /**
     * 每页显示条数，默认 10
     */
    protected long size = 10;

    /**
     * 当前页
     */
    protected long current = 1;

    /**
     * 排序字段信息
     */
    @Setter
    protected List<OrderItem> orders = new ArrayList<>();

    /**
     * 自动优化 COUNT SQL
     */
    protected boolean optimizeCountSql = true;
    /**
     * 是否进行 count 查询
     */
    protected boolean searchCount = true;
    /**
     *
     */
    @Setter
    protected boolean optimizeJoinOfCountSql = true;
    /**
     * 单页分页条数限制
     */
    @Setter
    protected Long maxLimit;
    /**
     * countId
     */
    @Setter
    protected String countId;

    /**
     * 是否分页
     */
    private Boolean pageIs = false;


    public <T> PageList(List<T> pageList, Class<E> convertClass) {
        this(pageList, convertClass, null);
    }

    public PageList(Page<E> page) {

        this.setCurrent(page.getCurrent());
        this.setTotal(page.getTotal());
        this.setSize(page.getSize());
        this.setCountId(page.countId());
        this.setMaxLimit(page.maxLimit());
        this.setOrders(page.orders());

        String pageIs = CommonServletUtil.getParamFromRequest("pageIs");
        if (ObjectUtil.isNull(pageIs)) {
            if (ObjectUtil.isNotNull(this.size) && this.size != Integer.MAX_VALUE) {
                pageIs = "true";
            }
        }
        this.setPageIs(BooleanUtil.toBoolean(pageIs));

        List<E> records = page.getRecords();
        this.addAll(records);
    }

    public <T> PageList(List<T> pageList, Class<E> convertClass, Function<T, E> function) {
        if (pageList instanceof PageList) {
            PageList pl = (PageList<Object>) pageList;
            this.setCurrent(pl.getCurrent());
            this.setTotal(pl.getTotal());
            this.setPageIs(pl.getPageIs());
            this.setSize(pl.getSize());
            if (ObjectUtil.isNotNull(pageList)) {
                List<E> collect = pageList.stream().map(v -> {
                    E t = null;
                    if (ObjectUtil.isNotNull(function)) {
                        t = function.apply(v);
                    } else {
                        if (ObjectUtil.isNotNull(convertClass)) {
                            try {
                                t = BeanUtil.copyProperties(v, convertClass);
                            } catch (Exception e) {
                                log.error("分页数据复制出错");
                            }
                        } else {
                            t = (E) v;
                        }
                    }
                    return t;
                }).collect(Collectors.toList());
                super.addAll(collect);
            }
        } else if (pageList instanceof PageResult<T> pl) {
            this.setCurrent(pl.getPage());
            this.setTotal(pl.getTotal());
            this.setPageIs(true);
            this.setSize(pl.getPageSize());
            if (ObjectUtil.isNotNull(pageList)) {
                List<E> collect = pageList.stream().map(v -> {
                    E t = null;
                    if (ObjectUtil.isNotNull(function)) {
                        t = function.apply(v);
                    } else {
                        if (ObjectUtil.isNotNull(convertClass)) {
                            try {
                                t = BeanUtil.copyProperties(v, convertClass);
                            } catch (Exception e) {
                                log.error("分页数据复制出错");
                            }
                        } else {
                            t = (E) v;
                        }
                    }
                    return t;
                }).collect(Collectors.toList());
                super.addAll(collect);
            }

        } else {
            this.setPageIs(false);
            List<E> collect = pageList.stream().map(v -> {
                E t = null;
                if (ObjectUtil.isNotNull(function)) {
                    t = function.apply(v);
                } else {
                    try {
                        t = BeanUtil.copyProperties(v, convertClass);
                    } catch (Exception e) {
                        log.error("分页数据复制出错");
                    }
                }
                return t;
            }).collect(Collectors.toList());
            super.addAll(collect);
        }
    }

    public static <T> PageList<T> valueOf(Page<T> page) {
        return new PageList(page);
    }

    public static <T, R> PageList<R> convert(List<T> page, Class<R> rClass) {
        if (ObjectUtil.isNull(page)) {
            page = Lists.newArrayList();
        }
        return new PageList<>(page, rClass, null);
    }

    public static <T, R> PageList<R> convert(List<T> page, Class<R> rClass, Function<T, R> function) {
        if (ObjectUtil.isNull(page)) {
            page = Lists.newArrayList();
        }
        return new PageList<>(page, rClass, function);
    }

    public static <T, R> PageList<R> of(List<T> page) {
        if (ObjectUtil.isNull(page)) {
            page = Lists.newArrayList();
        }
        return new PageList<>(page, null, null);
    }

    public static <T, R> List<R> toList(PageList<T> page, Class<R> convertClass, Function<T, R> function) {

        if (ObjectUtil.isNull(page)) {
            return Collections.emptyList();
        }
        return page.stream().map(v -> {
            R t = null;
            if (ObjectUtil.isNotNull(function)) {
                t = function.apply(v);
            } else {
                if (ObjectUtil.isNotNull(convertClass)) {
                    try {
                        t = BeanUtil.copyProperties(v, convertClass);
                    } catch (Exception e) {
                        log.error("分页数据复制出错");
                    }
                } else {
                    t = (R) v;
                }
            }
            return t;
        }).collect(Collectors.toList());

    }


    public void setList(List<E> list) {
        if (CollUtil.isEmpty(list)) {
            return;
        }
        this.addAll(list);
    }

    public static <T> PageList<T> of(List<T> records, Long total, Integer current, Integer size) {
        PageList<T> pageInfo = new PageList<>();
        pageInfo.setList(records);
        pageInfo.setTotal(total);
        pageInfo.setCurrent(current);
        pageInfo.setPageIs(true);
        pageInfo.setSize(size);
        return pageInfo;
    }
}
